package com.zuul.filter;

import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class ZuulFilterPost extends com.netflix.zuul.ZuulFilter {

    /**
     * 正常请求流程：
     *  请求到达首先会经过pre类型过滤器，而后到达route类型，进行路由，请求就到达真正的服务提供着，执行请求，
     *  返回结果后，会到达post过滤器，而后返回响应
     * 异常流程：
     *  整个过程中，pre或者route过滤器出现异常，都会直接进入error过滤器，在error处理完毕后，会将请求交给
     *  post过滤器，最后返回给用户
     *  如果是error过滤器自己出现异常，最终也会进入post过滤器，将最终的结果返回给请求客户端
     *  如果是post过滤器出现异常，会跳转到error过滤器，但是与pre和route不同的是，请求不会在到达post过滤器了
     *
     *  使用场景：
     *      例如：
     *          请求鉴权：一般会放在pre类型，如果发现没有访问权限，直接就拦截了
     *          异常处理：一般会在error类型和post类型过滤器中结合起来处理
     *          服务调用时长统计：pre和post结合使用
     */



    /**
     * 返回字符串，代表过滤的类型，包含以下四种：
     * pre: 请求在被路由之前执行
     * route: 在路由请求时调用
     * post: 在route和error过滤器之后执行
     * error: 处理请求是发生错误调用
     * @return
     */
    @Override
    public String filterType() {
        return "post";
    }

    /**
     * filteOrder: 通过返回int值来定义过滤器的执行顺序，数字越小优先级越大
     * @return
     */
    @Override
    public int filterOrder() {
        return 10;
    }

    /**
     * 过滤器是否生效  true/false
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 过滤器校验逻辑
     * 我们这里模拟   登陆路基 判断是否有token 有放行没有拦截
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        // 获取zuul提供的上下文对象
        RequestContext context = RequestContext.getCurrentContext();
        // 从上下文中获取http对象
        HttpServletRequest request = context.getRequest();
        // 从参数列表中获取token
        String token = request.getParameter("token");
        if(StringUtils.isBlank(token)){
            // 过滤改请求，不对其进行路由
            context.setSendZuulResponse(false);
            // 返回友好提示
            // 设置相应状态码
            context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
            // 设置响应信息
            context.setResponseBody("{\"code\":\"401\",\"text\":\"request error\"}");
        }
        context.set("token",token);
        return null;
    }
}
